#include "StompedReality/Core/Delegate.h"
#include <UnitTest++.h>
#include <functional>
#include <iostream>
class TestThing {
 private:

  int m_Y;
  int m_X;

 public:

  TestThing( int x ) {
    m_X = x;
    m_Y = x;
  }

  ~TestThing( ) {
  }

  int GetX( ) {
    return m_X;
  }

  void SetX( int x ) {
    this->m_X = x;
  }

  int GetY( ) {
    return m_Y;
  }

  void SetY( int y ) {
    this->m_Y = y;
  }

};

SUITE( Delegate_Test )
{
  TEST( Getter_Delegate_Test )
  {
    TestThing thing( 5 );
    TestThing thingB( 1 );
    std::function<int ( )> getterA = StompedReality::CreateDelegate( &thing, &TestThing::GetX );
    std::function<void (int)> setterA = StompedReality::CreateDelegate( &thing, &TestThing::SetX );
    std::function<int ( )> getterB = StompedReality::CreateDelegate( &thingB, &TestThing::GetX );
    std::function<void (int)> setterB = StompedReality::CreateDelegate( &thingB, &TestThing::SetX );
    CHECK_EQUAL( 5, thing.GetX( ));
    CHECK_EQUAL( 1, thingB.GetX( ));
    CHECK_EQUAL( 5, thing.GetY( ));
    CHECK_EQUAL( 1, thingB.GetY( ));
    CHECK_EQUAL( thing.GetX( ), getterA( ));
    CHECK_EQUAL( thingB.GetX( ), getterB( ));
    setterA( 17 );
    CHECK_EQUAL( 1, thingB.GetX( ));
    CHECK_EQUAL( 5, thing.GetY( ));
    CHECK_EQUAL( 1, thingB.GetY( ));
    setterB( -4 );
    CHECK_EQUAL( 5, thing.GetY( ));
    CHECK_EQUAL( 1, thingB.GetY( ));
    CHECK_EQUAL( 5, thing.GetY( ));
    CHECK_EQUAL( 1, thingB.GetY( ));

    std::function<void (int)> setterAY = StompedReality::CreateDelegate( &thing, &TestThing::SetY );
    setterAY( 4 );
    CHECK_EQUAL( 4, thing.GetY( ));
    CHECK_EQUAL( 1, thingB.GetY( ));
    CHECK_EQUAL( 17, thing.GetX( ));
    CHECK_EQUAL( -4, thingB.GetX( ));
    CHECK_EQUAL( thing.GetX( ), getterA( ));
    CHECK_EQUAL( thingB.GetX( ), getterB( ));
  }
}